﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Models;
using BLL;
namespace AGVControlSystemPro
{
    //【1】声明委托
    public delegate void ShowFileName(FileNameAddress objFileNameAddress);
    //声明打开工程文件的委托
    public delegate void OpenProject(FileNameAddress objFileNameAddress);
    public partial class FrmMapEdit : Form
    {
        private PictureFileManager objPictureFileManager = new PictureFileManager();//实例化图片加载业务
        private bool isAddPoint = false;  //是否激活添加节点
        private int landNum = 1;//地标号
        private List<LandNode> listLabel = new List<LandNode>(); //存储当前Label控件
        private FileNameAddress currentFileNameAddress = new FileNameAddress();//用来存储当前工程文件信息
        private PictureFile currentPictureFile = new PictureFile();//用来存储当前照片信息
        //画矩形定义的变量
        bool bDrawStart = false;
        Point pointStart = Point.Empty;
        Point pointContinue = Point.Empty;
        Dictionary<Point, Point> dicPoints;  

        public FrmMapEdit()
        {
            InitializeComponent();
            //画矩形变量初始化
            dicPoints = new Dictionary<Point, Point>();
            DoubleBuffered = true;
           this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true); 
           //控件属性初始化
           this.toolStrip1.Enabled = false;
           this.pictureBoxMap.Enabled = false;
        }

        #region 委托实体办法
        /// <summary>
        /// 接收委托传递的信息
        /// </summary>
        /// <param name="counter"></param>
        private void Receiver(FileNameAddress objFileNameAddress)
        {
            this.Text = "电子地图编辑（项目名称：" + objFileNameAddress.FileName + ")";
            //存储当前工程文件信息
            currentFileNameAddress.ID = objFileNameAddress.ID;
            currentFileNameAddress.FileName = objFileNameAddress.FileName;
        }
        /// <summary>
        /// 打开工程文件委托对应的实体办法
        /// </summary>
        /// <param name="objFileNameAddress"></param>
        private void OpenProjectReceiver(FileNameAddress objFileNameAddress)
        { 
            //【1】当前打开文件的显示
            this.Text = "电子地图编辑（项目名称：" + objFileNameAddress.FileName + ")";
            //存储当前工程文件信息
            currentFileNameAddress.ID = objFileNameAddress.ID;
            currentFileNameAddress.FileName = objFileNameAddress.FileName;
            //控件属性初始化
            this.toolStrip1.Enabled = true;
            this.pictureBoxMap.Enabled = true;
            //【2】加载图片
            LoadPicture(currentFileNameAddress.ID.ToString());
            //【3】加载地标

        }
        #endregion

        #region 数据初始化
        /// <summary>
        /// 根据工程ID加载图片
        /// </summary>
        /// <param name="id"></param>
        private void LoadPicture(string id)
        {
            try
            {
                currentPictureFile = objPictureFileManager.GetPictureById(id);
                //如果没有找到，既没有图片则显示默认图片
                if (currentPictureFile == null)
                {
                    this.pictureBoxMap.Image = Image.FromFile("default.png");
                    currentPictureFile = new PictureFile();//重新实例化，避免下面使用出现异常
                }
                else
                {
                    this.pictureBoxMap.Image = currentPictureFile.StuImage.Length != 0 ?
                        (Image)new Common.SerializeObjectToString().DeserializeObject(currentPictureFile.StuImage) : Image.FromFile("default.png");
                }
            }
            catch (Exception ex)
            {
                
                MessageBox.Show("图片加载异常，异常详细信息："+ex.Message);
            }
        }
        #endregion

        #region 菜单栏操作
        private void 导入图片LToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog objFileDialog = new OpenFileDialog();
            DialogResult result = objFileDialog.ShowDialog();
            if (result == DialogResult.OK)
                this.pictureBoxMap.Image = Image.FromFile(objFileDialog.FileName);
        }
        private void 新增NToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FrmNewMap objFrmNewMap = new FrmNewMap();
            //将从窗体的委托变量和主窗体的对应方法关联
            objFrmNewMap.msgSender = this.Receiver;
            DialogResult result = objFrmNewMap.ShowDialog();
            if(result == DialogResult.OK)
            {
                MessageBox.Show("创建成功","文件创建");
                this.pictureBoxMap.Image = null;//清除图片
                //控件属性初始化
                this.toolStrip1.Enabled = true;
                this.pictureBoxMap.Enabled = true;
            }
        }
        private void 打开OToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FrmMapOperation objFrmMapOperation = new FrmMapOperation();
            //将从窗体的委托变量和主窗体的对应方法关联
            objFrmMapOperation.openProjectSender = this.OpenProjectReceiver;
            objFrmMapOperation.ShowDialog();
        }
        #endregion

        #region 键值获取
        /// <summary>
        /// 获取按键值，并执行相应的操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmMapEdit_KeyPress(object sender, KeyPressEventArgs e)
        {
            //按下Backspace键
            if (e.KeyChar == 8)
            {
                for (int i = listLabel.Count -1; i >= 0; i--)
                {
                    if (listLabel[i].LableNode.BackColor == Color.IndianRed)
                    {
                        this.pictureBoxMap.Controls.Remove(listLabel[i].LableNode); //删除一个控件
                        listLabel.Remove(listLabel[i]); //删除集合中的控件
                    }
                }
            }
            //按下ESC键
            if (e.KeyChar == 27)
            {
                this.Cursor = Cursors.Default;
                isAddPoint = false;               
            }
           
        }
        private void FrmMapEdit_KeyDown(object sender, KeyEventArgs e)
        {
            //按下“上箭头”键
            if (e.KeyCode == Keys.Up)
            {               
                MoveUp();
            }
            //按下“下箭头”键
            if (e.KeyCode == Keys.Down)
            {
                MoveDown();
            }
            //按下“左箭头”键
            if (e.KeyCode == Keys.Left)
            {
                MoveLeft();
            }
            //按下“右箭头”键
            if (e.KeyCode == Keys.Right)
            {
                MoveRight();
            }
        }
        #region 地标控件上下左右移动

        private bool MoveUp()
        {
            foreach (LandNode item in listLabel)
            {
                if (item.LableNode.BackColor == Color.IndianRed) item.LableNode.Location = new Point(item.LableNode.Location.X, item.LableNode.Location.Y - 1); 
            }
            return true;
        }
        private bool MoveDown()
        {
            foreach (LandNode item in listLabel)
            {
                if (item.LableNode.BackColor == Color.IndianRed) item.LableNode.Location = new Point(item.LableNode.Location.X, item.LableNode.Location.Y + 1);
            }
            return true;
        }
        private bool MoveLeft()
        {
            foreach (LandNode item in listLabel)
            {
                if (item.LableNode.BackColor == Color.IndianRed) item.LableNode.Location = new Point(item.LableNode.Location.X-1, item.LableNode.Location.Y );
            }
            return true;
        }
        private bool MoveRight()
        {
            foreach (LandNode item in listLabel)
            {
                if (item.LableNode.BackColor == Color.IndianRed) item.LableNode.Location = new Point(item.LableNode.Location.X +1, item.LableNode.Location.Y);
            }
            return true;
        }
        #endregion

        #endregion

        #region 地标添加
        /// <summary>
        /// 点击鼠标提添加地标
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pictureBoxMap_MouseClick(object sender, MouseEventArgs e)
        {
            if (isAddPoint)
            {
                //鼠标左键按下则添加节点
                if (e.Button == MouseButtons.Left)
                {
                    //DrawPoint(this.pictureBoxMap, e.X - 5, e.Y - 5, 10);
                    DrawPoint(e.X - 10, e.Y - 10);
                }                 
                else  //鼠标右键按下则退出添加地标
                {
                    this.Cursor = Cursors.Default;
                    isAddPoint = false;
                }
            }            
        }
        /// <summary>
        /// 添加一个地标控件（Label）
        /// </summary>
        /// <param name="x">控件X轴坐标</param>
        /// <param name="y">控件Y轴坐标</param>
        /// <returns></returns>
        private bool DrawPoint(int x, int y)
        {
            Label objLabel = new Label();//创建一个Label控件对象
            objLabel.Size = new System.Drawing.Size(20, 20);
            objLabel.Location = new System.Drawing.Point(x, y);
            objLabel.Text = landNum.ToString();
            objLabel.Name = "lbl" + landNum.ToString();
            landNum++;//地标号增加
            objLabel.BackColor = Color.Red; //背景颜色
            objLabel.ForeColor = Color.White;//字体颜色
            objLabel.TextAlign = ContentAlignment.MiddleCenter;
            objLabel.AutoSize = false;
            objLabel.Font = new Font("宋体", 7, FontStyle.Regular); //第一个是字体，第二个大小，第三个是样式，
            objLabel.Click += objLabel_Click;
            objLabel.DoubleClick +=objLabel_DoubleClick;
            objLabel.MouseDown += objLabel_MouseDown;
            objLabel.MouseMove +=objLabel_MouseMove; 
            //人机界面添加一个Label控件
            this.pictureBoxMap.Controls.Add(objLabel); //添加一个控件
            //存储一个Label控件到list集合中
            listLabel.Add(new LandNode() {LandNum = landNum,NodeName = objLabel.Name,X = x,Y = y,LableNode = objLabel});
            //向数据库添加一个地标控件的详细信息
            return true;
        }    
        private byte DrawPoint(PictureBox pb, int x_point, int y_point, int wide)
        {
            Graphics g = pb.CreateGraphics();
            Pen pen = new Pen(Color.Black, 1);
            g.DrawEllipse(pen, x_point, y_point, wide, wide);
            g.FillEllipse(Brushes.Red, x_point, y_point, wide, wide);
            g.Dispose();
            return 1;
        }
        #endregion

        #region 添加的Label控件事件

        private Point movePoint; //鼠标拖动时初始坐标
        private void objLabel_MouseMove(object sender, MouseEventArgs e)
        {
           
            if (e.Button == MouseButtons.Left)
            {
                ((Label)sender).Location = new Point(((Label)sender).Location.X + e.X - movePoint.X, ((Label)sender).Location.Y + e.Y - movePoint.Y);
            }
        }
        private void objLabel_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                movePoint = e.Location;
            }
        }
        //控件单击事件
        private void objLabel_Click(object sender, EventArgs e)
        {
            Label objLabel = (Label)sender;
            // objLabel.BorderStyle = BorderStyle.Fixed3D;
            objLabel.BackColor = Color.IndianRed; //控件颜色变化，代表被选中
            //如果Ctrl和鼠标键同时按下则可以选择多个控件
            if ((Control.ModifierKeys & Keys.Control) == Keys.Control) ;
            else
            {
                foreach (LandNode item in listLabel)
                {
                    if (item.LableNode.Name != objLabel.Name) item.LableNode.BackColor = Color.Red;
                }
            }               
        }
        /// <summary>
        /// 添加控件的双击事件，主要用来设置地标控件属性
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void objLabel_DoubleClick(object sender, EventArgs e)
        {
           
        }
        #endregion

        #region 工具栏按键操作函数
        //新增节点，鼠标进入添加状态
        private void btnAddPoint_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Cross;
            isAddPoint = true;
        }
        /// <summary>
        /// 全部清空
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClear_Click(object sender, EventArgs e)
        {
            landNum = 1;//开始地标重新开始计数
            //【1】清空当前集合中所有数据
            listLabel.Clear();
            //【2】清空pictureBox的所有Label控件
            pictureBoxMap.Controls.Clear();
            //【3】清空数据库数据

        }
        /// <summary>
        /// 清除选择
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClearSelect_Click(object sender, EventArgs e)
        {
            foreach (LandNode item in listLabel)
            {
                if (item.LableNode.BackColor != Color.Red) item.LableNode.BackColor = Color.Red;
            }
        }
        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSave_Click(object sender, EventArgs e)
        {
            #region 数据验证
            if (pictureBoxMap.Image == null)
            {
                MessageBox.Show("保存失败，请导入线路图照片", "保存");
                return;
            }
            #endregion

            //数据封装
            PictureFile objPictureFile = new PictureFile()
            {
                StuImage = this.pictureBoxMap.Image != null ? new Common.SerializeObjectToString().SerializeObject(this.pictureBoxMap.Image) : "",
                ID = currentFileNameAddress.ID,
                PictureId =currentPictureFile !=null ? currentPictureFile.PictureId :0
            };
            //后台数据访问
            try
            {
                int result = new PictureFileManager().AddPictureFile(objPictureFile);
                if (result > 0)
                {
                    //当前照片数据保存
                    currentPictureFile.PictureId = result;
                    currentPictureFile.StuImage = objPictureFile.StuImage;
                    currentPictureFile.ID = objPictureFile.ID;
                    MessageBox.Show("保存成功", "保存");
                }
                else { MessageBox.Show("保存失败", "保存"); }
            }
            catch (Exception ex)
            {              
                MessageBox.Show("图片保存失败，错误详细信息："+ex.Message);
            }
        }
        #endregion

        #region 画矩形（区域选择）
        private void pictureBoxMap_Paint(object sender, PaintEventArgs e)
        {
            Pen pen = new Pen(Color.Black, 1f);
            pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
            if (bDrawStart)
            {
                //实时的画矩形  
                //int w = pointContinue.X - pointStart.X;
                //int h = pointContinue.Y - pointStart.Y;
                //if (w < 0) w = -w;
                //if (h < 0) h = -h;
                //Rectangle rect = new Rectangle(pointStart, new Size(w, h));
                Rectangle rect = new Rectangle();
                //【1】矩形起始坐标
                rect.Location = new Point(Math.Min(pointStart.X,pointContinue.X),Math.Min(pointStart.Y,pointContinue.Y));
                //【2】矩形的大小
                rect.Size = new Size(Math.Abs(pointStart.X - pointContinue.X),Math.Abs(pointStart.Y - pointContinue.Y));
                //【3】画矩形
                if (rect != null && rect.Width > 0 && rect.Height > 0) e.Graphics.DrawRectangle(pen, rect);        
                //【4】选中区域的控件颜色变化
                AreaSelection(pointStart, pointContinue); //选中区域
            }
            pen.Dispose();  
        }

        private void pictureBoxMap_MouseDown(object sender, MouseEventArgs e)
        {
            if (bDrawStart)
            {
                bDrawStart = false;
            }
            else
            {
                bDrawStart = true;
                pointStart = e.Location;
            }  
        }
        //坐标显示
        private void pictureBoxMap_MouseMove(object sender, MouseEventArgs e)
        {
            this.lblLocation.Text = "X:" + e.X.ToString() + "  Y:" + e.Y.ToString();
            if (bDrawStart)
            {
                pointContinue = e.Location;
                //Refresh();  
                this.pictureBoxMap.Invalidate();
            }  
        }
        private void pictureBoxMap_MouseUp(object sender, MouseEventArgs e)
        {
            if (bDrawStart)
            {
                //dicPoints.Add(pointStart, pointContinue);
               // AreaSelection(pointStart, pointContinue); //选中区域
                this.pictureBoxMap.Invalidate();
            }
            bDrawStart = false;
            
        }
        /// <summary>
        /// 区域选择
        /// </summary>
        /// <param name="startPoint">矩形 开始坐标</param>
        /// <param name="finishPoint">矩形介绍坐标</param>
        private void AreaSelection(Point startPoint, Point finishPoint)
        {
            //判断是否存在在矩形选中区域的Label控件
            foreach (LandNode item in listLabel)
            {
                //【1】有控件在选中区域内
                if (item.LableNode.Location.X >= Math.Min(startPoint.X, finishPoint.X) && item.LableNode.Location.X <= Math.Max(startPoint.X, finishPoint.X)
                    && item.LableNode.Location.Y >= Math.Min(startPoint.Y,finishPoint.Y) && item.LableNode.Location.Y <= Math.Max(finishPoint.Y,startPoint.Y))
                {
                    item.LableNode.BackColor = Color.IndianRed; //控件颜色变化，代表被选中
                }              
                else item.LableNode.BackColor = Color.Red; //该控件没有在选中区域内，则默认显示红色
            }
        }
        #endregion

        #region 退出操作
        private void 退出QToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void FrmMapEdit_FormClosing(object sender, FormClosingEventArgs e)
        {
            DialogResult result = MessageBox.Show("确认退出电子地图编辑界面吗？", "信息提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
            if (result == DialogResult.OK)
                FrmMain.objFrmMapEdit = null;
            else e.Cancel = true;
        }
        #endregion           
       
    }
}
